package com.gsy.springai1.controller;


import com.gsy.springai1.entity.vo.Result;
import com.gsy.springai1.repository.ChatHistoryRepository;
import com.gsy.springai1.repository.FileRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;
import org.springframework.ai.document.Document;
import org.springframework.ai.reader.ExtractedTextFormatter;
import org.springframework.ai.reader.pdf.PagePdfDocumentReader;
import org.springframework.ai.reader.pdf.config.PdfDocumentReaderConfig;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Flux;


import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Objects;

@Slf4j
@CrossOrigin("*")
@RestController
@RequestMapping("/ai/pdf")
@RequiredArgsConstructor
public class PdfController {

    private final FileRepository fileRepository;

    private final ChatHistoryRepository chatHistoryRepository;

    private final ChatClient pdfChatClient;

    private final VectorStore vectorStore;


    @RequestMapping(value = "/chat" ,produces = "text/html;charset=utf-8")
    public Flux<String> chat(String prompt , String  chatId){

        //1.找到会话文件
        Resource file = fileRepository.getFile(chatId);

        if (!file.exists()){
            //文件不存在，无法进行回答
            throw new RuntimeException("会话文件不存在！");
        }
        //1.保存会话id
        chatHistoryRepository.save("pdf", chatId);

        //2.请求模型
        return pdfChatClient.prompt()
                .user(prompt)
                .advisors(a ->a.param(AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY,chatId))
                .advisors(a -> a.param(QuestionAnswerAdvisor.FILTER_EXPRESSION, "file_name == '" +file.getFilename() +"'"))
                .stream()
                .content();

    }



    /**
     * 上传文件
     * @param chatId
     * @param file
     * @return
     */
    @RequestMapping("/upload/{chatId}")
    public Result uploadPdf(@PathVariable("chatId") String chatId , @RequestParam("file") MultipartFile file) {
        try {
            //1.首先判断是不是.pdf进行的结尾
            if(!Objects.equals(file.getContentType(), "application/pdf")){
                return Result.fail("只能上传pdf结尾的文件");
            }
            //2.保存文件
            boolean flag = fileRepository.save(chatId, file.getResource());
            if(!flag){
                return Result.fail("保存文件失败！");
            }

            //3.导入到向量数据库
            this.WriteToVectorStore(file.getResource());
            return Result.ok();
        } catch (Exception e) {
            log.error("Failed to upload pdf", e);
            return Result.fail("上传文件失败！");
        }
    }

    /**
     * 文件下载
     * @param chatId
     * @return
     */
    @GetMapping("/file/{chatId}")
    public ResponseEntity<Resource> download(@PathVariable("chatId") String  chatId) {
        //1.读取文件
        Resource resource = fileRepository.getFile(chatId);
        if(!resource.exists()){
            return ResponseEntity.notFound().build();
        }
        //2.文件名编码，写入响应头
        String filename = URLEncoder.encode(Objects.requireNonNull(resource.getFilename()), StandardCharsets.UTF_8);

        //3.返回文件
        return ResponseEntity.ok()
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .header("Content-Disposition", "attachment; filename = \"" + filename + "\"")
                .body(resource);
    }

    //将resource进入到向量数据库中
    public  void WriteToVectorStore(Resource resource){

        //1.创建pdf读取器
        PagePdfDocumentReader reader = new PagePdfDocumentReader(resource,
                PdfDocumentReaderConfig.builder()
                        .withPageExtractedTextFormatter(ExtractedTextFormatter.defaults())
                        .withPagesPerDocument(1)
                        .build());

        //2.读取pdf问加你，拆分为Doucment
        List<Document> documents = reader.read();

        //3.导入到向量数据库
        vectorStore.add(documents);

    }


}
